
static const float DEPTH_EPSILON = 0.001f;

cbuffer data :register(c0)
{
	float4x4 worldViewProj;
	float4x4 lightWorldViewProj;
};


Texture2D    diffuse     : register( t0 );

Texture2D    shadowMap     : register( t1 );


SamplerState samplerDiffuse : register( s0 )
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

SamplerState samplerShadowMap : register( s1 )
{
    Filter = MIN_MAG_MIP_POINT;
    AddressU = Clamp;
    AddressV = Clamp;
};


struct VS_INPUT
{
    float4 position			: POSITION;
    float2 texCoords		: TEXCOORD0;
    float3 normal			: NORMAL;
};

struct VS_OUTPUT
{
    float4 position : SV_POSITION;
    float2 texCoords : TEXCOORD0;
    float4 shadowMapCoords : TEXCOORD1;
};


VS_OUTPUT VSMain( VS_INPUT input )
{
    VS_OUTPUT Output;

    Output.position = mul(worldViewProj, input.position);
    Output.texCoords = input.texCoords;
    Output.shadowMapCoords = mul(lightWorldViewProj, input.position);

	return Output;
}

float CalcShadowFactor(float4 shadowCoords)
{
	shadowCoords.xyz /= shadowCoords.w;
	
	if (shadowCoords.x < -1 || shadowCoords.x > 1
		|| shadowCoords.y < -1 || shadowCoords.y > 1
		|| shadowCoords.z < 0 || shadowCoords.z > 1)
	{
		return 1.0f;;
	}
	
	float lightDepth = shadowCoords.z;
	
	float2 texCoords = float2(shadowCoords.x * 0.5f + 0.5f, shadowCoords.y * (- 0.5f) + 0.5f);

	float delta = 1.0f / 1024.0f;

	
	float shadowMapDepthTL = shadowMap.Sample( samplerShadowMap, float2(texCoords.x, texCoords.y) ).r;
	float shadowMapDepthTR = shadowMap.Sample( samplerShadowMap, float2(texCoords.x, texCoords.y) ).r;
	float shadowMapDepthBL = shadowMap.Sample( samplerShadowMap, float2(texCoords.x, texCoords.y) ).r;
	float shadowMapDepthBR = shadowMap.Sample( samplerShadowMap, float2(texCoords.x, texCoords.y) ).r;
	
	float resultTL = (lightDepth <= shadowMapDepthTL + DEPTH_EPSILON) * 0.5f + 0.5f;
	float resultTR = (lightDepth <= shadowMapDepthTR + DEPTH_EPSILON) * 0.5f + 0.5f;
	float resultBL = (lightDepth <= shadowMapDepthBL + DEPTH_EPSILON) * 0.5f + 0.5f;
	float resultBR = (lightDepth <= shadowMapDepthBR + DEPTH_EPSILON) * 0.5f + 0.5f;

	float result = lerp( lerp(resultTL, resultTR, 0.5f), lerp(resultBL, resultBR, 0.5f), 0.5f);
	
	return result;
	
}

float4 PSMain( VS_OUTPUT input ) : SV_TARGET
{
	float shadowFactor = CalcShadowFactor(input.shadowMapCoords);
	
	return shadowFactor * diffuse.Sample( samplerDiffuse, float2(input.texCoords.x, input.texCoords.y) );
}